package com.xiaoyun.service.impl;

import com.xiaoyun.enums.MsgActionEnum;
import com.xiaoyun.enums.MsgSignFlagEnum;
import com.xiaoyun.enums.SearchFriendsStatusEnum;
import com.xiaoyun.mapper.*;
import com.xiaoyun.netty.ChatMsg;
import com.xiaoyun.netty.DataContent;
import com.xiaoyun.netty.UserChannelRel;
import com.xiaoyun.pojo.FriendsRequest;
import com.xiaoyun.pojo.MyFriends;
import com.xiaoyun.pojo.Users;
import com.xiaoyun.pojo.bo.UserSearchBO;
import com.xiaoyun.pojo.vo.FriendRequestVO;
import com.xiaoyun.pojo.vo.MyFriendsVO;
import com.xiaoyun.service.UserService;
import com.xiaoyun.utils.FastDFSClient;
import com.xiaoyun.utils.FileUtils;
import com.xiaoyun.utils.JsonUtils;
import com.xiaoyun.utils.QRCodeUtils;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.util.Date;
import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    private final UsersMapper usersMapper;

    private final Sid sid;

    private final QRCodeUtils qrCodeUtils;

    private final FastDFSClient fastDFSClient;

    private final MyFriendsMapper myFriendsMapper;

    private final UsersMapperCustom usersMapperCustom;

    private final FriendsRequestMapper friendsRequestMapper;

    private final ChatMsgMapper chatMsgMapper;

    @Autowired
    public UserServiceImpl(UsersMapper usersMapper, Sid sid, QRCodeUtils qrCodeUtils, FastDFSClient fastDFSClient, MyFriendsMapper myFriendsMapper, UsersMapperCustom usersMapperCustom, FriendsRequestMapper friendsRequestMapper, ChatMsgMapper chatMsgMapper) {
        this.usersMapper = usersMapper;
        this.sid = sid;
        this.qrCodeUtils = qrCodeUtils;
        this.fastDFSClient = fastDFSClient;
        this.myFriendsMapper = myFriendsMapper;
        this.usersMapperCustom = usersMapperCustom;
        this.friendsRequestMapper = friendsRequestMapper;
        this.chatMsgMapper = chatMsgMapper;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public boolean queryUsernameIsExist(String username) {
        Users user = new Users();
        user.setUsername(username);
        Users result = usersMapper.selectOne(user);

        return result != null ? true : false;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Users queryUserForLogin(String username, String pwd) {
        Example userExample = new Example(Users.class);
        Example.Criteria criteria = userExample.createCriteria();
        criteria.andEqualTo("username", username);
        criteria.andEqualTo("password", pwd);
        Users result = usersMapper.selectOneByExample(userExample);
        return result;
    }

    @Override
    public Users saveUser(Users user) {
        String userId = sid.nextShort();
        String qrCodePath = "F://user" + userId + "qrcode.png";

        qrCodeUtils.createQRCode(qrCodePath, "muxin_qrcode:" + user.getUsername());
        MultipartFile qrCodeFile = FileUtils.fileToMultipart(qrCodePath);

        String qrCodeUrl = "";
        try {
            qrCodeUrl = fastDFSClient.uploadBase64(qrCodeFile);
        } catch (IOException e) {
            e.printStackTrace();
        }

        user.setQrcode(qrCodeUrl);

        user.setId(userId);
        usersMapper.insert(user);
        return user;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Users updateUserInfo(Users user) {
        usersMapper.updateByPrimaryKeySelective(user);
        return queryUserById(user.getId());
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public SearchFriendsStatusEnum preconditionSearchFriends(UserSearchBO userSearchBO) {

        Users users = queryUserInfoByUsername(userSearchBO.getFriendUsername());
        if (users == null) {
            return SearchFriendsStatusEnum.USER_NOT_EXIST;
        }
        if (users.getId().equals(userSearchBO.getMyUserId())) {
            return SearchFriendsStatusEnum.NOT_YOURSELF;
        }
        Example mfe = new Example(MyFriends.class);
        Example.Criteria mfc = mfe.createCriteria();
        mfc.andEqualTo("myUserId", userSearchBO.getMyUserId());
        mfc.andEqualTo("myFriendUserId", users.getId());
        MyFriends myFriendsRel = myFriendsMapper.selectOneByExample(mfe);
        if (myFriendsRel != null) {
            return SearchFriendsStatusEnum.ALREADY_FRIENDS;
        }
        return SearchFriendsStatusEnum.SUCCESS;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Users queryUserInfoByUsername(String username) {
        Example ue = new Example(Users.class);
        Example.Criteria uc = ue.createCriteria();
        uc.andEqualTo("username", username);
        return usersMapper.selectOneByExample(ue);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void sendFriendRequest(UserSearchBO userSearchBO) {
        String friendUsername = userSearchBO.getFriendUsername();
        String myUserId = userSearchBO.getMyUserId();
        Users friend = queryUserInfoByUsername(friendUsername);
        Example fre = new Example(FriendsRequest.class);
        Example.Criteria frc = fre.createCriteria();
        frc.andEqualTo("sendUserId", myUserId);
        frc.andEqualTo("acceptUserId", friend.getId());
        FriendsRequest request = friendsRequestMapper.selectOneByExample(fre);
        if (request == null) {
            String requestId = sid.nextShort();
            request.setId(requestId);
            request.setSendUserId(myUserId);
            request.setAcceptUserId(friend.getId());
            request.setRequestDateTime(new Date());
            friendsRequestMapper.insert(request);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public List<FriendRequestVO> queryFriendRequestList(String acceptUserId) {
        return usersMapperCustom.queryFriendRequestList(acceptUserId);
    }

    @Override
    public void deleteFriendRequest(String sendUserId, String acceptUserId) {
        Example fre = new Example(FriendsRequest.class);
        Example.Criteria frc = fre.createCriteria();
        frc.andEqualTo("sendUserId", sendUserId);
        frc.andEqualTo("acceptUserId", acceptUserId);
        friendsRequestMapper.deleteByExample(fre);

    }

    @Override
    public void passFriendRequest(String sendUserId, String acceptUserId) {
        saveFriends(sendUserId, acceptUserId);
        saveFriends(acceptUserId, sendUserId);
        deleteFriendRequest(sendUserId, acceptUserId);

        Channel sendChannel = UserChannelRel.get(sendUserId);
        if (sendChannel != null) {
            DataContent dataContent = new DataContent();
            dataContent.setAction(MsgActionEnum.PULL_FRIEND.type);
            sendChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContent)));
        }

    }

    @Override
    public List<MyFriendsVO> queryMyFriend(String userId) {
        return usersMapperCustom.queryMyFriends(userId);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public String saveMsg(ChatMsg chatMsg) {
        com.xiaoyun.pojo.ChatMsg msgDB = new com.xiaoyun.pojo.ChatMsg();
        String msgId = sid.nextShort();
        msgDB.setId(msgId);
        msgDB.setAcceptUserId(chatMsg.getReceiverId());
        msgDB.setSendUserId(chatMsg.getSenderId());
        msgDB.setCreateTime(new Date());
        msgDB.setSignFlag(MsgSignFlagEnum.unsign.type);
        msgDB.setMsg(chatMsg.getMsg());
        chatMsgMapper.insert(msgDB);
        return msgId;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void updateMshSigned(List<String> msgIdList) {
        usersMapperCustom.batchUpdateMsgSigned(msgIdList);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public List<com.xiaoyun.pojo.ChatMsg> getUnReadMsgList(String acceptUserId) {
        Example chatExample = new Example(com.xiaoyun.pojo.ChatMsg.class);
        Example.Criteria chatExampleCriteria = chatExample.createCriteria();

        chatExampleCriteria.andEqualTo("signFlag", 0);
        chatExampleCriteria.andEqualTo("acceptUserId", acceptUserId);
        List<com.xiaoyun.pojo.ChatMsg> result = chatMsgMapper.selectByExample(chatExample);
        return result;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void saveFriends(String sendUserId, String acceptUserId) {
        MyFriends myFriends = new MyFriends();
        String recordId = sid.nextShort();
        myFriends.setId(recordId);
        myFriends.setMyFriendUserId(acceptUserId);
        myFriends.setMyUserId(sendUserId);
        myFriendsMapper.insert(myFriends);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public Users queryUserById(String userId) {
        return usersMapper.selectByPrimaryKey(userId);
    }

}
